package liu.de.util;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.util.Pair;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

/**
 * @author liude
 */
@Slf4j
@Setter
public class HttpUtil<R> {
    private static final String HTTP_PREFIX = "http";
    private RestTemplate restTemplate;

    //    private MultiValueMap<String, String> query;
//
//    private Map<String, String> headers;
//
//    private Object body;
//
//    private HttpMethod httpMethod;
//
//    private Pair<String, String> basicAuth;
//
//    private static HttpUtil builder = new HttpUtil();
    private String url;

    public ResponseEntity<R> get() {
        Assert.notNull(restTemplate, "");
        Assert.notNull(url, "");
        return execute(restTemplate, HttpMethod.GET, url, null, null, null, null);
//        return execute(restTemplate, HttpMethod.GET, url, query, headers, body, basicAuth);
    }

//    public ResponseEntity<R> post() {
//        Assert.notNull(restTemplate, "");
//        Assert.notNull(url, "");
//        return execute(restTemplate, HttpMethod.POST, url, query, headers, body, basicAuth);
//    }

    private ResponseEntity<R> execute(RestTemplate restTemplate, HttpMethod method, String urlOrPath, MultiValueMap<String, String> query,
                                      Map<String, String> headers, Object body, Pair<String, String> basicAuth) {

        log.debug("method={}, urlOrPath={}, query={}, headers={}, body={}, basicAuth={}", method, urlOrPath, query, headers, body, basicAuth);

        UriComponentsBuilder uriComponentsBuilder;

        if (urlOrPath.toLowerCase().startsWith(HTTP_PREFIX)) {
            uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(urlOrPath);
        } else {
            uriComponentsBuilder = UriComponentsBuilder.fromPath(urlOrPath);
        }

        if (Objects.nonNull(query)) {
            uriComponentsBuilder.queryParams(query);
        }
        String uri = uriComponentsBuilder.toUriString();

        HttpHeaders httpHeaders = new HttpHeaders();
        if (Objects.nonNull(headers)) {
            headers.forEach(httpHeaders::add);
        }

        if (Objects.nonNull(basicAuth)) {
            String token = Base64Utils.encodeToString((basicAuth.getFirst() + ":" + basicAuth.getSecond()).getBytes(StandardCharsets.UTF_8));
            httpHeaders.add("Authorization", "Basic " + token);
        }

        HttpEntity<Object> entity;
        if (method.equals(HttpMethod.GET)) {
            entity = new HttpEntity<>(httpHeaders);
        } else {
            entity = new HttpEntity<>(body, httpHeaders);
        }

        log.debug("actual http: method={}, uri={}, entity={}", method, uri, entity);

        return restTemplate
                .exchange(uri,
                        method,
                        entity,
                        new ParameterizedTypeReference<R>() {
                        });
    }
}
